﻿using Hydrogen.ULib.Attributes;
using Hydrogen.ULib.DataStructure;
using Hydrogen.ULib.Extends;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;

namespace Hydrogen.MarkovChain.SolidMap2DScene
{
    public interface IMap
    {
        void SetColor(int x, int y, SolidType type);
        SolidType GetColor(int x, int y);
    }

    /// <summary>
    /// 管理地图
    /// </summary>
    public class Map : MonoBehaviour, IMap
    {
        private Tilemap _tileMap;
        private SolidMap2dResManager _resMgr;

        private SolidCacheBase _solidCache = new SolidCache();

        private void Awake()
        {
            this.GetComponentInChild("Grid/Tilemap", out this._tileMap);
        }

        public void Init(SolidMap2dResManager resMgr)
        {
            this._resMgr = resMgr;
        }
        public void SetColor(Vector3Int pos, SolidType type)
            => SetColor(pos.x, pos.y, type);
        public void SetColor(Vector2Int pos, SolidType type)
            => SetColor(pos.x, pos.y, type);
        private Vector3Int _tempV3;
        public void SetColor(int x, int y, SolidType type)
        {
            // 将缓存里的当前位置的颜色去掉
            var solid = GetColor(x, y);
            this._solidCache.RemoveSolid(solid, x, y);

            this._tempV3.x = x;
            this._tempV3.y = y;
            this._tileMap.SetTile(this._tempV3, this._resMgr.GetTile(type));

            // 把新设置的颜色放入缓存
            this._solidCache.SetSolid(type, x, y);
        }

        public SolidType GetColor(Vector2Int pos) => GetColor(pos.x, pos.y);
        public SolidType GetColor(int x, int y)
        {
            this._tempV3.x = x;
            this._tempV3.y = y;
            var tile = this._tileMap.GetTile<SolidTile>(this._tempV3);
            if (tile == null) return SolidType.None;

            //if (Enum.TryParse(tile.name, true, out SolidType type))
            //    return type;
            //return SolidType.None;
            return tile.Type;
        }

        public bool IsColor(int x, int y, SolidType type)
            => GetColor(x, y) == type;

        public void ResetMap()
        {
            this._solidCache.Clear();

            int width = 20;
            int height = 20;
            // 四条边界
            for (int x = -width; x <= width; x++)
            {
                SetColor(x, height, SolidType.P);
                SetColor(x, -height, SolidType.P);
            }
            for (int y = -height; y <= height; y++)
            {
                SetColor(-width, y, SolidType.P);
                SetColor(width, y, SolidType.P);
            }

            // 内部填充黑色
            for (int x = -(width - 1); x <= width - 1; x++)
                for (int y = -(height - 1); y <= (height - 1); y++)
                    SetColor(x, y, SolidType.B);
        }

        /// <summary>
        /// 设置初始点
        /// </summary>
        /// <param name="sps"></param>
        internal void SetSP(params RuleSP[] sps)
        {
            foreach (var item in sps)
            {
                if (item == null) continue;
                SetColor(item.Pos, item.SolidType);
            }
        }

        public bool TryExcute(IRuleNodeSolidReplace solidReplace)
        {
            if (solidReplace == null || solidReplace.In == null)
                return false;

            // 获取第一个颜色
            SolidType solid = solidReplace.In.GetDatumSolid();

            // 找到第一个颜色所在的所有位置，打乱顺序的
            var list = this._solidCache.GetSolidPos(solid, true);

            // 逐个判定，如果可以执行就执行，不能就下一个
            Direction dir;
            foreach (var item in list)
            {
                if (solidReplace.In.IsMatch(this, item.x, item.y, out dir))
                {
                    solidReplace.Out?.SetColor(this, item.x, item.y, dir);
                    return true;
                }
            }

            // 都不能，就是执行失败
            return false;
        }

        #region 测试
#if UNITY_EDITOR
        [Space, Header("测试")]
        [Button("ResetMap"), SerializeField]
        private bool _testResetMap;

#endif
        #endregion
    }
}